/*
****************************************************************************************************************
*= = 版权信息：Copyright (C) 356 - 999. Ombres Industry Empiral. All rights reserved.
*= = 文件名称：Hollow.h
*= = 功能描述：工业系统电力协议声明文件
*= = 编写人员：Carlyon W. Tung
****************************************************************************************************************
*/

#ifndef __HOLLOW_H__
#define __HOLLOW_H__

#ifdef  __cplusplus
extern "C" {
#endif // End of __cplusplus

/*
*===============================================================================================================
*= = 声明文件
*===============================================================================================================
*/

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __INSIGHT_OS_WINDOWS__
#include <io.h>
#include <process.h>
#include <Windows.h>
#else
#include <unistd.h>
#endif

#ifdef __INSIGHT_OS_LINUX__
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#endif

#include <pthread.h>
#include <semaphore.h>

#ifdef __HAVE_SSL_SUPPORT__
#include <openssl/conf.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#endif

#ifdef __ORCINUS_USE_BOOST__
//
#endif

/*
*===============================================================================================================
*= = 宏定义
*===============================================================================================================
*/

#define MAX_BUFFER_SIZE     0xFFFF

#ifdef __INSIGHT_OS_LINUX__
#define MAX_CONNECTIONS     SOMAXCONN
#else
#define MAX_CONNECTIONS     0xFFFF
#endif

/* socket events */
#define SE_CONNECT          0
#define SE_DISCONNECT       1
#define SE_READ             2
#define SE_ERROR            3
#define SE_LISTEN           4
#define SE_CLOSE            5
#define SE_ACCEPT           6

/* socket flags */
#define SF_IPV6             0x01
#define SF_NONBLOCKING      0x02
#ifdef __HAVE_SSL_SUPPORT__
#define SF_SSL              0x04
#endif

#define __ORCINUS_BY_MUTEX__

#ifdef __ORCINUS_BY_MUTEX__
typedef pthread_mutex_t     syncobj_t;
#define sync_init(obj)      pthread_mutex_init(obj, NULL)
#define sync_lock(obj)      pthread_mutex_lock(obj)
#define sync_try_lock(obj)  pthread_mutex_trylock(obj)
#define sync_unlock(obj)    pthread_mutex_unlock(obj)
#define sync_free(obj)      pthread_mutex_destroy(obj)
#else
typedef sem_t               syncobj_t;
#define sync_init(obj)      sem_init(obj, 0, 1)
#define sync_lock(obj)      sem_wait(obj)
#define sync_try_lock(obj)  sem_trywait(obj)
#define sync_unlock(obj)    sem_post(obj)
#define sync_free(obj)      sem_destroy(obj)
#endif

#ifdef __INSIGHT_OS_WINDOWS__
    #ifndef INET_ADDRSTRLEN
        #define INET_ADDRSTRLEN     22
    #endif

    #ifndef INET6_ADDRSTRLEN
        #define INET6_ADDRSTRLEN    65
    #endif

    #define MSG_NOSIGNAL            0
#endif

#ifdef __INSIGHT_OS_WINDOWS__
int sockets_init(void);
void sockets_free(void);
#else
#define sockets_init() 0
#define sockets_free() ;
#endif // End of __INSIGHT_OS_WINDOWS__

#ifdef __HAVE_SSL_SUPPORT__
#define SSL_SERVER_METHOD TLSv1_2_server_method
#define SSL_CLIENT_METHOD TLSv1_2_client_method
#define SSL_SERVER_METHOD SSLv23_server_method
#define SSL_CLIENT_METHOD SSLv23_client_method
#endif

#ifdef __ORCINUS_USE_BOOST__
//
#endif

/*
*===============================================================================================================
*= = 结构体定义
*===============================================================================================================
*/

typedef void* client_t;
typedef void* server_t;
typedef void* connection_t;
typedef void* synctimer_t;

typedef struct socket_event {
    int type;
    connection_t connection;
    union {
        server_t server;
        client_t client;
    };
    union {
        struct {
            char* buffer;
            int len;
        } io;
        int error;
    };
} event_t;

/*
*===============================================================================================================
*= = 类型定义
*===============================================================================================================
*/

typedef void (*listener_t)(event_t*);
typedef void (*timer_func_t)();

/*
*===============================================================================================================
*= = 函数定义
*===============================================================================================================
*/

server_t server_new(const char* addr, const int port, const int flags, syncobj_t* sync);
void server_free(const server_t server);
int server_start(const server_t server);
void server_stop(const server_t server);
int server_started(const server_t server);
void server_lock(const server_t server);
void server_unlock(const server_t server);
void server_wait(const server_t server);
void server_set_listener(const server_t server, listener_t listener);
int server_get_count(const server_t server);
connection_t server_get_connection(const server_t server, const int index);
int server_get_index(const server_t server, const connection_t connection);
void* server_get_data(const server_t server);
void server_set_data(const server_t server, void* data);
int server_get_handle(const server_t server);
int server_get_info(const server_t server, char* addr, int* port, int* ipv6);

void connection_close(connection_t connection);
int connection_write(const connection_t connection, const void* buffer, const size_t len, int* result);
void* connection_get_data(const connection_t connection);
void connection_set_data(const connection_t connection, void* data);
long long int connection_received(const connection_t connection);
long long int connection_transmitted(const connection_t connection);
struct sockaddr_in* connection_get_peer(const connection_t connection);
struct sockaddr_in6* connection_get_peer6(const connection_t connection);
const char* connection_get_address(const connection_t connection);
unsigned short connection_get_lport(const connection_t connection);
unsigned short connection_get_rport(const connection_t connection);
server_t connection_get_server(const connection_t connection);
time_t connection_get_time(const connection_t connection);

client_t client_new(const char* addr, const int port, const int flags, syncobj_t* sync);
void client_free(const client_t client);
int client_open(const client_t client);
void client_close(const client_t client);
int client_try_open(const client_t client);
int client_connected(const client_t client);
int client_write(const client_t client, const void* buffer, const size_t len, int* result);
connection_t client_get_connection(const client_t client);
void client_set_listener(const client_t client, listener_t listener);
void client_wait(const client_t client);
void client_lock(const client_t client);
void client_unlock(const client_t client);
const void* client_get_data(const client_t client);
void client_set_data(const client_t client, void* data);
int client_get_port(const client_t client);
char* client_get_addr(const client_t client);

int msleep(int msec);

synctimer_t timer_new(timer_func_t listener, const int timeout, syncobj_t* sync);
int timer_start(synctimer_t timer);
void timer_stop(synctimer_t timer);
void timer_free(synctimer_t timer);
void timer_wait(synctimer_t timer);

#ifdef __HAVE_SSL_SUPPORT__
void ssl_init();
void ssl_free();
void ssl_set_certificates(const char* keyfile, const char* certfile);
char* ssl_error(int errcode);
#endif

#ifdef __ORCINUS_USE_BOOST__
//
#endif


#ifdef  __cplusplus
}
#endif // End of __cplusplus

#endif // End of __HOLLOW_H__


/*
****************************************************************************************************************
*= = 文件结束
****************************************************************************************************************
*/


